﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
using Sharp.Infrastructure.Search;
using Sharp.Portal.Interface;
using Sharp.Portal.Mvc.List;
using Sharp.Portal.Other;

namespace Sharp.Portal.AdminLTE.Provider
{
    /// <summary>
    /// 列表页适配器
    /// </summary>
    public class ListPage : ITemplateProvider
    {
        private static readonly CamelCasePropertyNamesContractResolver Cpncr =
            new CamelCasePropertyNamesContractResolver();

        /// <summary>
        /// 获取模板
        /// </summary>
        /// <param name="model">模型</param>
        /// <param name="isMobileDevice">是否移动设备</param>
        /// <returns></returns>
        public string GetTemplate(object model, bool isMobileDevice)
        {
            if (model == null)
            {
                return string.Empty;
            }

            var dataList = (BSSharpList)model;
            //dataList.IsMobileDevice = isMobileDevice;
            dataList.InitComplete();

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("@model {0}\r\n", model.GetType().FullName);


            if (dataList.Layout != null)
            {
                sb.AppendLine("@{");
                sb.AppendFormat("Layout = \"{0}\";\r\n", dataList.Layout.LayoutPath);
            }
            else
            {
                sb.AppendLine("@if (ViewBag.IsPjaxRequest == false)");
                sb.AppendLine("{");
                sb.AppendLine("Layout = \"~/Areas/Platform/Views/Shared/__Layout.cshtml\";");
            }
            sb.AppendLine("}");
            if (dataList.Layout != null)
            {
                sb.AppendFormat("@section {0}{{\r\n", dataList.Layout.SectionName);
            }
            sb.AppendLine("<section class=\"content-header\">");
            sb.AppendLine("<h1>@Model.PageTitle</h1>");

            if (dataList.Breadcrumb.IsNotNullOrEmpty())
            {
                sb.AppendLine(dataList.Breadcrumb);
            }

            sb.AppendLine("</section>");
            sb.AppendLine("<section class=\"content\">");
            sb.AppendLine("<div class=\"box box-primary container\">");
            sb.AppendLine("<div class=\"box-header with-border\">");

            if (!dataList.Feature.HasFlag(ListFeature.HiddenToolButton))
            {
                sb.AppendLine("<div class=\"row\">");
                sb.AppendLine("<div class=\"dataTable-tools btn-group col-md-8 col-sm-12 no-padding\">");

                //渲染工具栏按钮
                var toolButtons = string.Join("\r\n", dataList.ToolButtons.Select(x => x.Value.Html));
                sb.AppendLine(toolButtons);
                sb.AppendLine("</div>");
            }


            sb.AppendLine("<div class=\"box-tools SearchArea col-md-4 col-sm-12\">");
            sb.AppendLine("<div class=\"input-group input-group-sm defaultSearch\">");

            foreach (var column in dataList.QueryItems) //渲染默认查询项
            {
                if (column.QueryFeatureOption.HasFlag(QueryFeature.DefualtQuery))
                {
                    sb.AppendFormat(
                        "<input type =\"text\" name=\"{0}\" autocomplete=\"off\" class=\"form-control pull-right\" placeholder=\"{1}\">\r\n",
                        column.Name, column.Text);
                    break;
                }
            }

            sb.AppendLine("<div class=\"input-group-btn\">");
            sb.AppendFormat(
                "<button type =\"button\" class=\"btn btn-default\" onclick=\"window.app.search(this);\" data-search = \"#{0}\"><i class=\"fa fa-search\"></i></button>\r\n",
                dataList.ListControlId);
            if (dataList.QueryItems.Any(x => !x.QueryFeatureOption.HasFlag(QueryFeature.DefualtQuery)))
            {
                sb.AppendFormat(
                    "<button type=\"button\" class=\"btn btn-default\" title=\"高级查询\" id=\"{0}-toggle-advanced-search\"><i class=\"fa fa-angle-double-down\"></i></button>",
                    dataList.ListControlId);
            }
            sb.AppendLine("</div>");
            sb.AppendLine("</div>");
            sb.AppendLine("</div>");
            sb.AppendLine("</div>");

            //渲染默认查询项之外的组合查询
            var queryItems = dataList.QueryItems.Where(x =>
                !x.QueryFeatureOption.HasFlag(QueryFeature.DefualtQuery) &&
                x.QueryFeatureOption.HasFlag(QueryFeature.Queryable)).ToArray();
            if (queryItems.Any())
            {
                sb.AppendFormat(
                    "<div id=\"{0}-div-advanced-search\" class=\"row SearchArea\" style=\"display: none;\">",
                    dataList.ListControlId);
                sb.AppendLine("<form class=\"form-inline well-sm\" style=\"line-height:40px;\">");
                var optimizeIndex = 0;
                foreach (var queryColumn in queryItems)
                {
                    if (queryColumn.IsHiddenField) continue;

                    sb.AppendFormat("@if(this.CheckFieldPermission(\"{0}\")) {{\r\n", queryColumn.Name);
                    sb.AppendFormat(
                        "<div class=\"col-md-4 col-sm-6\"><label class=\"col-lg-5 col-sm-5 text-right control-label\">{0}：</label>",
                        queryColumn.Text.IsNullOrEmpty() ? queryColumn.Name : queryColumn.Text);

                    sb.Append("<div class=\"col-lg-7 col-sm-7\">");
                    if (!queryColumn.MasterDataCategory.IsNullOrEmpty())
                    {
                        //if (queryColumn.IsTree)
                        //{
                        //    sb.AppendFormat(
                        //        "<div class=\"input-group\"><input id=\"{1}Text\" class=\"form-control\" readonly=\"readonly\" type=\"text\" /><span class=\"input-group-addon\"><i class=\"fa fa-check\" id=\"{1}Trigger\"></i></span> @Html.HiddenFor(m => m.{0})\r\n<div id=\"{1}MenuContent\" class=\"menuContent\" style=\"display: none; position: absolute; display: none; right: 15px; top: 33px; z-index: 1000;\">\r\n<ul id=\"{1}_Treemenu\" class=\"ztree\" style=\"margin-top: 0; width: 260px;\"></ul></div></div>\r\n<script type = \"text/javascript\">\r\nvar data = @MvcHtmlString.Create(Sharp.Portal.Platform.GetMasterData(\"{2}\").ToJson());\r\nvar {1}List = new app.TreeList();\r\n{1}List.init(data.children, \"{1}\", \"@Model.{0}\");\r\n</script>",
                        //        queryColumn.Name, queryColumn.Name.Replace(".", "_"), queryColumn.MasterDataCategory);
                        //}
                        //else
                        {
                            sb.AppendFormat(
                                "@Html.Bootstrap().DropdownListFor(x => x.{0}).DataSource(Sharp.Portal.Platform.GetMasterData(\"{1}\")).DisplayField(\"Name\").ValueField(\"Code\").Multiple()\r\n",
                                queryColumn.Name, queryColumn.MasterDataCategory);

                        }
                    }
                    else if (!queryColumn.DisplayField.IsNullOrEmpty())
                    {
                        if (queryColumn.IsTree)
                        {
                            sb.AppendLine("<div class=\"form-group\">");
                            sb.AppendFormat(
                                " <div class=\"input-group\"><input id=\"{1}Text\" class=\"form-control\" readonly=\"readonly\" type=\"text\" /><span class=\"input-group-addon\"><i class=\"fa fa-check\" id=\"{1}Trigger\"></i></span></div> <input id=\"{1}\" name=\"{2}\" type=\"hidden\" />\r\n<div id=\"{1}MenuContent\" class=\"menuContent\" style=\"display: none; position: absolute; display: none; right: 15px; top: 33px; z-index: 1000;\">\r\n<ul id=\"{1}_Treemenu\" class=\"ztree\" style=\"margin-top: 0; width: 260px;\"></ul></div></div>\r\n<script type = \"text/javascript\">\r\nvar data = @MvcHtmlString.Create(Model.{0}.ToJson());\r\nvar {1}List = new app.TreeList();\r\n{1}List.init(data.children, \"{1}\", \"\",\"{3}\",\"{4}\");\r\n</script>",
                                queryColumn.Name, queryColumn.Name.Replace(".", "_"), queryColumn.SearchFor,
                                Cpncr.GetResolvedPropertyName(queryColumn.DisplayField),
                                Cpncr.GetResolvedPropertyName(queryColumn.ValueField));
                        }
                        else
                        {
                            sb.AppendFormat(
                                "@Html.Bootstrap().DropdownList(\"\").Name(\"{0}\").DataSource(Model.{1}).DisplayField(\"{2}\").ValueField(\"{3}\").Multiple()\r\n",
                                queryColumn.SearchFor, queryColumn.Name, queryColumn.DisplayField,
                                queryColumn.ValueField);
                        }
                    }
                    else if (queryColumn.Feature.HasFlag(ColumnFeature.BooleanColumn))
                    {
                        sb.AppendFormat(
                            "<div class=\"radio-inline form-control\"><label class=\"radio-inline\"><input name=\"{0}\" type=\"radio\" value=\"1\" />是</label> <label class=\"radio-inline\"><input name=\"{0}\" type=\"radio\" value=\"0\" />否</label></div>\r\n",
                            queryColumn.Name);
                    }
                    else if (queryColumn.Feature.HasFlag(ColumnFeature.NumberColumn))
                    {
                        sb.AppendFormat("<div class=\"input-group\">@Html.Bootstrap().TextBox().Name(\"{0}_from\").InputType(\"Number\")\r\n",
                            queryColumn.SearchFor);
                        sb.Append("<div class=\"input-group-addon\">-</div>");
                        sb.AppendFormat("@Html.Bootstrap().TextBox().Name(\"{0}_to\").InputType(\"Number\")</div>\r\n",
                            queryColumn.SearchFor);
                    }
                    else if (queryColumn.Feature.HasFlag(ColumnFeature.DateColumn))
                    {
                        sb.AppendFormat(
                            "<div class=\"input-group input-daterange\" id=\"search_{0}\"><input type=\"text\" class=\"form-control\" name=\"{1}_from\" id=\"{0}_from\"><div class=\"input-group-addon\">-</div><input type=\"text\" class=\"form-control\" name=\"{1}_to\" id=\"{0}_to\"></div>\r\n",
                         queryColumn.Name, queryColumn.SearchFor);
                        sb.AppendFormat(
                            "<script> $('#search_{0}').daterangepicker({{ autoUpdateInput: false,autoApply:false,locale:$.fn.daterangepicker.zh_CN_locale}}, function (start, end, label) {{ this.autoUpdateInput=true;$(\"#{0}_from\").val(start.format('YYYY-MM-DD')); $(\"#{0}_to\").val(end.format('YYYY-MM-DD')); }});</script>\r\n", queryColumn.Name);
                    }
                    else
                    {
                        sb.AppendFormat(
                            "<input type=\"text\" name=\"{0}\" placeholder=\"{1}\" class=\"form-control\">\r\n",
                            queryColumn.SearchFor, queryColumn.Text);
                    }

                    //针对下拉框进行的优化设置

                    if (queryColumn.QueryFeatureOption.HasFlag(QueryFeature.EqualMatchString))
                    {
                        sb.AppendFormat("<input type =\"hidden\" name=\"Optimizes[{0}].Field\" value=\"{1}\" />\r\n",
                            optimizeIndex, queryColumn.Name);
                        sb.AppendFormat(
                            "<input type =\"hidden\" name=\"Optimizes[{0}].OldComparisonType\" value=\"{1}\" />\r\n",
                            optimizeIndex, (int)ComparisonType.Like);
                        sb.AppendFormat(
                            "<input type =\"hidden\" name=\"Optimizes[{0}].OptimizeComparisonType\" value=\"{1}\" />\r\n",
                            optimizeIndex, (int)ComparisonType.Equal);
                        optimizeIndex++;
                    }



                    sb.AppendLine("</div>");
                    sb.AppendLine("</div>");
                    sb.AppendLine("}");
                }

                sb.AppendFormat(
                    "<div class=\"col-md-4 col-sm-6 text-center\"><span class=\"col-sm-5\"></span><div class=\"btn-group\"><button id=\"btn-advanced-search\" class=\"btn btn-success\" type=\"button\" data-search=\"#{0}\" onclick=\"window.app.search(this);\"><i class=\"fa fa-search\"></i> 查询</button><button type=\"reset\" class=\"btn btn-default\" onclick=\"window.app.searchRseset(this);\"><i class=\"fa fa-eraser\"></i> 重置</button></div></div>",
                    dataList.ListControlId);


                foreach (var property in dataList.QueryItems.Where(q => q.IsHiddenField))
                {
                    switch (property.ValueFrom)
                    {
                        case QueryItem.ValueFromType.ValueFromRequest:
                            sb.AppendFormat(
                                " <input name=\"{2}\" data-original=\"{0}\" type=\"hidden\" value=\"@Request.Params[\"{1}\"]\" />",
                                property.Name, property.ValueFromName,property.SearchFor);
                            break;
                        case QueryItem.ValueFromType.ValueFromModel:
                            sb.AppendFormat(
                                "<input name=\"{2}\" data-original=\"{0}\" type=\"hidden\" value=\"@Convert.ToString(Model.{1})\" />",
                                property.Name, property.ValueFromName, property.SearchFor);
                            break;
                        case QueryItem.ValueFromType.DefaultValue:
                            sb.AppendFormat("<input name=\"{2}\" data-original=\"{0}\" type=\"hidden\" value=\"{1}\" />", property.Name,
                                property.QueryDefaultValue, property.SearchFor);
                            break;
                    }
                    sb.AppendLine();
                }

                sb.AppendLine("</form></div>");

                sb.AppendFormat(
                    "<script> $(\"#{0}-toggle-advanced-search\").click(function () {{ $(\"i\", this).toggleClass(\"fa-angle-double-down fa-angle-double-up\"); $(\"#{0}-div-advanced-search\").slideToggle(\"fast\"); }});</script>",
                    dataList.ListControlId);
            }

            sb.AppendLine("</div>");
            sb.AppendLine("<div class=\"box-body no-padding\">");


            sb.AppendLine("<div class=\"table-responsive\">");
            sb.AppendFormat(
                "<table id =\"{0}\" class=\"table table-bordered table-condensed table-striped table-hover dataTable text-center display nowrap\" width=\"100%\"></table>\r\n",
                dataList.ListControlId);
            sb.AppendLine("</div></div></div>");
            sb.AppendLine("</section>");
            if (dataList.HasLockColumn())
            {
                sb.AppendFormat("<style> #{0} th, #{0} td {{  white-space: nowrap; }} </style>",
                    dataList.ListControlId);
            }
            if (dataList.ImportJavascript.IsNotNullOrEmpty())
            {
                if (dataList.ImportJavascript.StartsWith("~") || dataList.ImportJavascript.StartsWith(@"\"))
                {
                    sb.AppendFormat("<script src=\"{0}\"></script>\r\n", dataList.ImportJavascript);
                }
            }
            if (dataList.ImportCss.IsNotNullOrEmpty())
            {
                if (dataList.ImportCss.StartsWith("~") || dataList.ImportCss.StartsWith(@"\"))
                {
                    sb.AppendFormat("<link href=\"{0}\" rel=\"stylesheet\" />\r\n", dataList.ImportCss);
                }
            }

            sb.AppendLine("<script type=\"text/javascript\">");
            sb.AppendLine("$(document).ready(function () {");

            sb.AppendFormat("var $dataList = $('#{0}').dataTable({{", dataList.ListControlId);
            sb.Append("\"serverSide\": true, responsive : @Model.Responsive.ToString().ToLower(),\r\n");
            if (!dataList.Feature.HasFlag(ListFeature.Paging))
            {
                sb.AppendLine(" paging : false ,info: false,");
            }

            if (dataList.HasLockColumn())
            {
                //sb.AppendLine("scrollY: '60vh',");
                sb.AppendLine("scrollX: '100%',");
                //sb.AppendLine("scrollCollapse: true,");

                //sb.AppendLine("sScrollXInner: '200%',"); //好像没用了。
                sb.AppendFormat("fixedColumns: {{ leftColumns : {0} , heightMatch: 'none' }},\r\n",
                    dataList.LockLeftColumns());
            }
            if (dataList.Feature.HasFlag(ListFeature.MultiSelect) && !isMobileDevice)
            {
                sb.AppendLine("select: { style: 'multi', selector: 'td:first-child' },");
            }
            if (dataList.Feature.HasFlag(ListFeature.MultiSelect) && isMobileDevice)
            {
                sb.AppendLine("select: { style: 'multi' },");
            }
            sb.AppendLine("displayLength:@Model.GetPageSizeDefine() ,");
            sb.AppendLine("\"ajax\": { \"url\": \"@Url.Action(\"" +
                          string.Join("\",\"", dataList.StoreUrlAction.Split(',')) + "\")\", \"type\": \"POST\" },");
            sb.AppendLine("\"columnDefs\": [ { sDefaultContent: '', aTargets: ['_all'] }");
            sb.AppendLine("],");
            sb.AppendLine("columns: [");

            if (dataList.Feature.HasFlag(ListFeature.MultiSelect) && !isMobileDevice)
            {
                sb.AppendLine(
                    "{ title: '<label class=\"checkbox select-checkbox\"><input type=\"checkbox\" id=\"" +
                dataList.ListControlId + "checkAllItem\" onclick=\"window.app.checkAllItem(\\'" +
                    dataList.ListControlId +
                    "\\',this);\" /><i></i></label>', data: null, sortable: false, width: 30 ,\"sClass\":'checkColumn select-checkbox'},");
            }
            if (dataList.Feature.HasFlag(ListFeature.RowNumber) && !isMobileDevice)
            {
                sb.AppendLine(
                    "{ title:'序号',data : null, bSortable : false, targets : 0, width : 50 ,\"sClass\":'rowNumberColumn',render : function(data, type, row, meta) { var startIndex = meta.settings._iDisplayStart; return startIndex + meta.row + 1; }},");
            }

            foreach (var column in dataList.ColumnItems)
            {
                if (column.Hidden) continue;
                var jsonName = Cpncr.GetResolvedPropertyName(column.DataIndex);

                var plist = new List<string> { $"title: \"{column.Text}\"" };
                if (!column.MasterDataCategory.IsNullOrEmpty())
                {
                    plist.Add(
                        $"data : \"{jsonName}\",render : function (data, type, row, meta) {{ return app.code2Text(\"{column.MasterDataCategory}\", row.{jsonName}); }}");
                }
                else if (column.Feature.HasFlag(ColumnFeature.DateColumn)
                         && !column.Format.IsNullOrEmpty())
                {
                    plist.Add(
                        $"data: \"{jsonName}\", render : function (data, type, row, meta) {{ if(data) return moment(row.{jsonName}).format('{column.Format}'); else return ''; }}");
                }
                else if (column.Feature.HasFlag(ColumnFeature.TemplateColumn))
                {
                    if (column.Template.IsNullOrEmpty())
                    {
                        throw new NotSupportedException("模板列未定义模板");
                    }
                    plist.Add($"render: {column.Template}");
                }
                else if (column.Feature.HasFlag(ColumnFeature.TreeColumn))
                {
                    if (column.Template.IsNotNullOrEmpty())
                    {
                        plist.Add($"render: {column.Template}");
                    }
                    else
                    {
                        plist.Add($"data: \"{jsonName}\"");
                    }
                }
                else if (column.Feature.HasFlag(ColumnFeature.BooleanColumn))
                {
                    plist.Add(
                        $"data: \"{jsonName}\", render : function (data, type, row, meta) {{ if(data==null) return ''; else return data ? \"{column.TrueText}\" : \"{column.FalseText}\" }}");
                }
                else if (column.Feature.HasFlag(ColumnFeature.NumberColumn))
                {
                    plist.Add($"data: \"{jsonName}\"");
                }
                else
                {
                    if (column.Width == 0)
                        plist.Add($"data: \"{jsonName}\"");
                    else
                        plist.Add(
                            $"data: \"{jsonName}\", render : function (data, type, row, meta) {{ var content = ''; if(data) content=data; return '<div style=\"width:{column.Width}px;overflow: hidden;text-overflow: ellipsis;\" ' + 'title=\"'+ content +'\">'+ content +'</div>'; }}");
                }
                if (column.Width > 0)
                    plist.Add($"width: {column.Width}");

                plist.Add($"\"sClass\": \"{column.Align.ToString().ToLower()}\"");
                plist.Add($"sortable: {column.Sortable.ToString().ToLower()}");

                //加上权限判断
                sb.AppendFormat("@if (this.CheckFieldPermission(\"{0}\")) {{\r\n", jsonName);
                sb.AppendFormat("\t\t@:{{ {0}}},\r\n", string.Join(",", plist.ToArray()));
                sb.AppendLine("}");
            }

            sb.AppendLine("]");

            sb.AppendLine(@",""createdRow"": function ( row, data, index,cells ) {");

            #region 行绘制颜色

            var index = 0;
            if (dataList.Feature.HasFlag(ListFeature.MultiSelect))
            {
                index++;
            }
            if (dataList.Feature.HasFlag(ListFeature.RowNumber))
            {
                index++;
            }
            foreach (var column in dataList.ColumnItems)
            {
                if (column.Hidden) continue;

                foreach (var item in column.ClientDrawRows)
                {
                    sb.AppendFormat("\tif({0}) {{\r\n", item.Key
                        .Replace("{text}", "$(cells[" + index + "]).text()")
                        .Replace("{data}", "data[" + index + "]"));

                    sb.AppendFormat("$(row).addClass('{0}')", item.Value.ToString());
                    sb.AppendLine("\t}");

                }
                index++;
            }

            #endregion

            sb.AppendLine("}");
            sb.AppendLine("});");


            //if (dataList.Feature.HasFlag(ListFeature.MultiSelect))
            //{

            //    sb.AppendLine("$dataList.on( 'deselect', function ( e, dt, type, indexes ) { ");
            //    sb.AppendLine("$($dataList.attr('id')+'checkAllItem').find('thead .select-checkbox').attr('checked','');");
            //    sb.AppendLine("});");
            //}
            sb.AppendLine("});");
            sb.AppendLine("</script>");
            if (dataList.Layout != null)
            {
                sb.AppendLine("}");
            }


            return sb.ToString();
        }
    }
}